package controllers

import (
	"admin-glm-go/internal/models"
	"admin-glm-go/internal/response"
	"admin-glm-go/internal/utils"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// MenuListRequest 菜单列表请求参数
type MenuListRequest struct {
	Page     int    `form:"page"`
	PageSize int    `form:"pageSize"`
	Name     string `form:"name"`
	Type     int    `form:"type"`
}

// AddMenuRequest 添加菜单请求参数
type AddMenuRequest struct {
	Name       string `json:"name" binding:"required"`
	Type       int    `json:"type" binding:"required"`
	Icon       string `json:"icon"`
	Path       string `json:"path"`
	Component  string `json:"component"`
	Permission string `json:"permission"`
	Sort       int    `json:"sort"`
	ParentID   uint64 `json:"parentId"`
	Status     int    `json:"status"`
	Visible    int    `json:"visible"`
}

// UpdateMenuRequest 更新菜单请求参数
type UpdateMenuRequest struct {
	ID         uint64 `json:"id" binding:"required"`
	Name       string `json:"name" binding:"required"`
	Type       int    `json:"type" binding:"required"`
	Icon       string `json:"icon"`
	Path       string `json:"path"`
	Component  string `json:"component"`
	Permission string `json:"permission"`
	Sort       int    `json:"sort"`
	ParentID   uint64 `json:"parentId"`
	Status     int    `json:"status"`
	Visible    int    `json:"visible"`
}

// MenuController 菜单控制器
type MenuController struct {
	db *gorm.DB
}

// NewMenuController 创建菜单控制器
func NewMenuController(db *gorm.DB) *MenuController {
	return &MenuController{db: db}
}

// GetMenuList 获取菜单列表
// @Summary 获取菜单列表
// @Description 获取菜单列表
// @Tags 菜单管理模块
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param page query int false "页码"
// @Param pageSize query int false "每页数量"
// @Param name query string false "菜单名称"
// @Param type query int false "菜单类型"
// @Success 200 {object} response.Response
// @Router /menu/list [get]
func (ctrl *MenuController) GetMenuList(c *gin.Context) {
	var req MenuListRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		response.ParamError(c)
		return
	}

	// 设置默认值
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}

	// 构建查询条件
	query := ctrl.db.Model(&models.Menu{})
	if req.Name != "" {
		query = query.Where("name LIKE ?", "%"+req.Name+"%")
	}
	if req.Type != 0 {
		query = query.Where("type = ?", req.Type)
	}

	// 获取总数
	var total int64
	query.Count(&total)

	// 分页查询
	var menus []models.Menu
	offset := (req.Page - 1) * req.PageSize
	err := query.Offset(offset).Limit(req.PageSize).Order("sort ASC, id ASC").Find(&menus).Error
	if err != nil {
		response.ServerError(c)
		return
	}

	// 构建响应数据
	var records []gin.H
	for _, menu := range menus {
		record := gin.H{
			"id":         menu.ID,
			"name":       menu.Name,
			"type":       menu.Type,
			"icon":       menu.Icon,
			"path":       menu.Path,
			"component":  menu.Component,
			"permission": menu.Permission,
			"sort":       menu.Sort,
			"parentId":   menu.ParentID,
			"status":     menu.Status,
			"visible":    menu.Visible,
			"createTime": menu.CreateTime.Format("2006-01-02 15:04:05"),
			"updateTime": menu.UpdateTime.Format("2006-01-02 15:04:05"),
		}
		records = append(records, record)
	}

	response.PageSuccess(c, total, records, req.Page, req.PageSize)
}

// GetMenuTree 获取菜单树
// @Summary 获取菜单树
// @Description 获取菜单树
// @Tags 菜单管理模块
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Success 200 {object} response.Response
// @Router /menu/tree [get]
func (ctrl *MenuController) GetMenuTree(c *gin.Context) {
	var menus []models.Menu
	if err := ctrl.db.Where("visible = ?", 1).Order("sort ASC, id ASC").Find(&menus).Error; err != nil {
		response.ServerError(c)
		return
	}

	// 构建树形结构
	tree := buildMenuTree(menus, 0)

	response.Success(c, tree)
}

// buildMenuTree 构建菜单树
func buildMenuTree(menus []models.Menu, parentId uint64) []gin.H {
	var tree []gin.H

	for _, menu := range menus {
		if menu.ParentID == parentId {
			node := gin.H{
				"id":         menu.ID,
				"name":       menu.Name,
				"type":       menu.Type,
				"icon":       menu.Icon,
				"path":       menu.Path,
				"component":  menu.Component,
				"permission": menu.Permission,
				"sort":       menu.Sort,
				"parentId":   menu.ParentID,
				"status":     menu.Status,
				"visible":    menu.Visible,
				"createTime": menu.CreateTime.Format("2006-01-02 15:04:05"),
				"updateTime": menu.UpdateTime.Format("2006-01-02 15:04:05"),
			}

			// 递归构建子节点
			children := buildMenuTree(menus, menu.ID)
			if len(children) > 0 {
				node["children"] = children
			}

			tree = append(tree, node)
		}
	}

	return tree
}

// GetUserMenu 获取用户菜单
// @Summary 获取用户菜单
// @Description 获取用户菜单
// @Tags 菜单管理模块
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Success 200 {object} response.Response
// @Router /menu/user-menu [get]
func (ctrl *MenuController) GetUserMenu(c *gin.Context) {
	// 获取当前用户ID
	userId, exists := c.Get("userId")
	if !exists {
		response.Unauthorized(c)
		return
	}

	// 查询用户
	var admin models.Admin
	if err := ctrl.db.Preload("Roles.Permissions").First(&admin, userId).Error; err != nil {
		response.ServerError(c)
		return
	}

	// 收集权限编码
	var permissionCodes []string
	for _, role := range admin.Roles {
		for _, permission := range role.Permissions {
			permissionCodes = append(permissionCodes, permission.Code)
		}
	}

	// 去重
	permissionCodes = utils.UniqueString(permissionCodes)

	// 查询有权限的菜单
	var menus []models.Menu
	if err := ctrl.db.Where("visible = ? AND status = ?", 1, 1).Order("sort ASC, id ASC").Find(&menus).Error; err != nil {
		response.ServerError(c)
		return
	}

	// 过滤有权限的菜单
	var filteredMenus []models.Menu
	for _, menu := range menus {
		if menu.Permission == "" || utils.ContainsString(permissionCodes, menu.Permission) {
			filteredMenus = append(filteredMenus, menu)
		}
	}

	// 构建树形结构
	tree := buildMenuTree(filteredMenus, 0)

	response.Success(c, tree)
}

// AddMenu 添加菜单
// @Summary 添加菜单
// @Description 添加菜单
// @Tags 菜单管理模块
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param body body AddMenuRequest true "菜单信息"
// @Success 200 {object} response.Response
// @Router /menu/add [post]
func (ctrl *MenuController) AddMenu(c *gin.Context) {
	var req AddMenuRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.ParamError(c)
		return
	}

	// 检查菜单名称是否已存在
	var count int64
	if err := ctrl.db.Model(&models.Menu{}).Where("name = ?", req.Name).Count(&count).Error; err != nil {
		response.ServerError(c)
		return
	}
	if count > 0 {
		response.Error(c, 400, "菜单名称已存在")
		return
	}

	// 如果有父级ID，检查父级是否存在
	if req.ParentID > 0 {
		var parent models.Menu
		if err := ctrl.db.First(&parent, req.ParentID).Error; err != nil {
			response.Error(c, 400, "父级菜单不存在")
			return
		}
	}

	// 创建菜单
	menu := models.Menu{
		Name:       req.Name,
		Type:       req.Type,
		Icon:       req.Icon,
		Path:       req.Path,
		Component:  req.Component,
		Permission: req.Permission,
		Sort:       req.Sort,
		ParentID:   req.ParentID,
		Status:     req.Status,
		Visible:    req.Visible,
	}

	// 保存菜单
	if err := ctrl.db.Create(&menu).Error; err != nil {
		response.ServerError(c)
		return
	}

	response.Success(c, nil)
}

// UpdateMenu 更新菜单
// @Summary 更新菜单
// @Description 更新菜单
// @Tags 菜单管理模块
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param body body UpdateMenuRequest true "菜单信息"
// @Success 200 {object} response.Response
// @Router /menu/update [put]
func (ctrl *MenuController) UpdateMenu(c *gin.Context) {
	var req UpdateMenuRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.ParamError(c)
		return
	}

	// 查询菜单
	var menu models.Menu
	if err := ctrl.db.First(&menu, req.ID).Error; err != nil {
		response.NotFound(c)
		return
	}

	// 检查菜单名称是否已存在（排除自己）
	var count int64
	if err := ctrl.db.Model(&models.Menu{}).Where("name = ? AND id != ?", req.Name, req.ID).Count(&count).Error; err != nil {
		response.ServerError(c)
		return
	}
	if count > 0 {
		response.Error(c, 400, "菜单名称已存在")
		return
	}

	// 如果有父级ID，检查父级是否存在且不能是自己或自己的子级
	if req.ParentID > 0 {
		// 不能设置自己为父级
		if req.ParentID == req.ID {
			response.Error(c, 400, "不能设置自己为父级")
			return
		}

		// 检查父级是否存在
		var parent models.Menu
		if err := ctrl.db.First(&parent, req.ParentID).Error; err != nil {
			response.Error(c, 400, "父级菜单不存在")
			return
		}

		// 检查是否设置自己的子级为父级（防止循环引用）
		var childIds []uint64
		getAllChildMenuIds(ctrl.db, req.ID, &childIds)
		if utils.ContainsUint64(childIds, req.ParentID) {
			response.Error(c, 400, "不能设置自己的子级为父级")
			return
		}
	}

	// 更新菜单信息
	menu.Name = req.Name
	menu.Type = req.Type
	menu.Icon = req.Icon
	menu.Path = req.Path
	menu.Component = req.Component
	menu.Permission = req.Permission
	menu.Sort = req.Sort
	menu.ParentID = req.ParentID
	menu.Status = req.Status
	menu.Visible = req.Visible

	// 保存菜单
	if err := ctrl.db.Save(&menu).Error; err != nil {
		response.ServerError(c)
		return
	}

	response.Success(c, nil)
}

// DeleteMenu 删除菜单
// @Summary 删除菜单
// @Description 删除菜单
// @Tags 菜单管理模块
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param id path int true "菜单ID"
// @Success 200 {object} response.Response
// @Router /menu/delete/{id} [delete]
func (ctrl *MenuController) DeleteMenu(c *gin.Context) {
	id := utils.StringToUint64(c.Param("id"))
	if id == 0 {
		response.ParamError(c)
		return
	}

	// 查询菜单
	var menu models.Menu
	if err := ctrl.db.First(&menu, id).Error; err != nil {
		response.NotFound(c)
		return
	}

	// 检查是否有子菜单
	var count int64
	if err := ctrl.db.Model(&models.Menu{}).Where("parent_id = ?", id).Count(&count).Error; err != nil {
		response.ServerError(c)
		return
	}
	if count > 0 {
		response.Error(c, 400, "请先删除子菜单")
		return
	}

	// 删除菜单
	if err := ctrl.db.Delete(&menu).Error; err != nil {
		response.ServerError(c)
		return
	}

	response.Success(c, nil)
}

// getAllChildMenuIds 获取所有子菜单ID
func getAllChildMenuIds(db *gorm.DB, parentId uint64, childIds *[]uint64) {
	var children []models.Menu
	if err := db.Where("parent_id = ?", parentId).Find(&children).Error; err != nil {
		return
	}

	for _, child := range children {
		*childIds = append(*childIds, child.ID)
		getAllChildMenuIds(db, child.ID, childIds)
	}
}